// EvaluatingPlayerList.cpp : implementation of the CEvaluatingPlayerList class
//
#include "EvaluatingPlayerList.h"

#include <math.h>
#include "Common/Support/Debug.h"


#include <string>
#include <fstream>

using namespace std;


// Vypocita kvadraticku rovnicu ax^2 + bx + c = 0
double CalculateQuadraticEquation(double a, double b, double c, double& lfRoot1, double& lfRoot2)
{
	double discr = pow(b,2) - 4*a*c;
	
	if (discr > 0)
	{
		lfRoot1 = (-b + sqrt(discr)) / (2*a);
		lfRoot2 = (-b - sqrt(discr)) / (2*a);
	}
	else if(discr == 0)
	{
		lfRoot1 = -b / (2*a);
	}

	return discr;
}

// --------------------------------------------------------------------------------------------------------- //

CEvaluatingPlayerList::~CEvaluatingPlayerList()
{
	RemoveOldPlayerInformation(0);
}

// --------------------------------------------------------------------------------------------------------- //

bool CEvaluatingPlayerList::AnyoneInAreaRadius(Point position, double lfRadius)
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);
		Point playerPos(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition());
		
		if((playerPos - position).GetLength() <= lfRadius) return true;
	}

	return false;
}

// --------------------------------------------------------------------------------------------------------- //

// Vypocita vhodnu poziciu v okoli hraca pre normalnu nahravku. Vrati false, ak sa taka pozicia nenajde.
bool CEvaluatingPlayerList::CalculateNormalPassPosition(double lfMyselfPosX, double lfMyselfPosY, double& lfPassPosX, double& lfPassPosY)
{
/*	clock_t start, finish;
	start = clock();
*/
	
	// Definovanie jedneho z X moznych prihravacich bodov
	typedef struct PassPoint
	{
		double lfX;
		double lfY;
	} PASSPOINT;

	// Oblast prihravky (polomer)
	double lfPassAreaRadius;

	// Potencialni hraci pre normalnu prihravku
	int nPassCandidates = 0;
	CEvaluatingPlayer* passCandidates[11]; PassPoint bestPasses[11]; double bestEvaluatingPasses[11];

	memset(passCandidates, 0, sizeof(passCandidates));

	CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();

//	ofstream out("Normalne prihravanie.txt", ios::app); // Zapis do suboru

	PredictNextPositions();
			
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		if((*evPlayerIterator)->GetPlayerType() == PT_OUR)
		{		
			CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);
			
			double lfDistance = pEvPanesMap->CalculatePaneDistanceFromPlayer(lfMyselfPosX, lfMyselfPosY, pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition());
			
			// Ak sa nachadza nas v nasom pokutovom uzemi (a kusok za nim), tak mu urcite nenahram, lebo by som mohol ohrozit
			// nasu branku. Takto sa vyhnem aj nahravkam brankarovi, ktore su zakazane (pravidlo "Mala domov").
			if(pEvPanesMap->IsInRectArea(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), -nOriginalPlaygroundWidth/2.0, -22, -30, 22))
				continue;

			// Prihravat sa moze iba vo vzdialenosti v intevale (lfMinPassDistance, lfMaxPassDistance)
			if((lfDistance <= lfMinPassDistance) || (lfDistance >= lfMaxPassDistance))
				continue;

			// Polomer oblasti prihravania zavisi od vzdialenosti prihravajuceho hraca
			// Cim musi prihravka prekonat vacsiu vzdialenost, tym sa musi prehladat viacero prihravacich pozicii 
			// Namapujem interval <lfMinPassDistance, lfMaxPassDistance> na <lfMinPassAreaRadius, lfMaxPassAreaRadius>
			lfPassAreaRadius = (lfDistance - lfMinPassDistance) / (lfMaxPassDistance - lfMinPassDistance) * (lfMaxPassAreaRadius - lfMinPassAreaRadius) +  lfMinPassAreaRadius;

			// Priesecniky kruznice (oblasti prihravky) a priamky (nahravka)
			double lfIntersectX1, lfIntersectY1, lfIntersectX2, lfIntersectY2; 

			// X-ova zlozka normaloveho vektora
			double lfNormalX, lfNormalY;
			// Y-ova zlozka normalovheo vektora
	
			// Vypocitaju sa zlozky normaloveho vektora medzi hracom s loptou a potencionalnym kandidatom
			lfNormalX = pEvPlayer->GetPlayerXPosition() - lfMyselfPosX;
			lfNormalY = pEvPlayer->GetPlayerYPosition() - lfMyselfPosY;

			// Vseobecna rovnica priamky (ax + by + c = 0)
			// a,b, c - koeficienty	
			double a = lfNormalX;
			double b = lfNormalY;
			double c = -(a * pEvPlayer->GetPlayerXPosition()) - (b * pEvPlayer->GetPlayerYPosition());
	
			// Ak je smernica priamky definovana (t.j. priamka nie je rovnobezna s osou x)
			if(b != 0)
			{
				// Korene kvadratickej rovnice
				double x1, x2; 
				
				// Vypocitaju sa koeficienty parametrickej rovnice priamky (y = kx + q)
				double k = (-a/b);
				double q = (-c/b);
			
				// Vypocitaju sa koeficienty kvadratickej rovnice (Ax + By + C = 0)
				double A = 1 + pow(k, 2);
				double B = -2 * pEvPlayer->GetPlayerXPosition() + 2 * k * (q - pEvPlayer->GetPlayerYPosition());
				double C = pow(pEvPlayer->GetPlayerXPosition(),2) + pow((q - pEvPlayer->GetPlayerYPosition()), 2) - pow(lfPassAreaRadius,2);

				// Vypocita sa priesecnik kruznice a priamky
				double lfDiscr = CalculateQuadraticEquation(A, B, C, x1, x2);

				// 2 priesecniky
				if(lfDiscr > 0)
				{
					lfIntersectX1 = x1;
					lfIntersectY1 = k * x1 + q;
					lfIntersectX2 = x2; 
					lfIntersectY2 = k * x2 + q;
/*
					CString strTmp;
  					strTmp.Format("Koren 1: %lf, Koren 2: %lf", x1, x2);
					AfxMessageBox(strTmp);
*/				}
				// 1 priesecnik (dotycnica), rydzokvadraticka rovnica
				else if(lfDiscr = 0)
				{
					lfIntersectX1 = lfIntersectX2 = x1;
					lfIntersectY1 = lfIntersectY2 = k * x1 + q;
				}
				// Kvadraticka rovnica nema riesenie (diskriminant < 0)
				else
					continue;
			}	
			// Smernica priamky nie je definovana	
			else
			{
				lfIntersectX1 = pEvPlayer->GetPlayerXPosition();
				lfIntersectY1 = pEvPlayer->GetPlayerYPosition() + lfPassAreaRadius;
				lfIntersectX2 = pEvPlayer->GetPlayerXPosition();
				lfIntersectY2 = pEvPlayer->GetPlayerYPosition() - lfPassAreaRadius;
			}
			
			bool bEnemiesInTriangle = false;
			for(list<CEvaluatingPlayer*>::iterator evPlayerIterator2 = GetEvPlayerIteratorBegin(); evPlayerIterator2 != GetEvPlayerIteratorEnd(); evPlayerIterator2++)
			{		
				if((*evPlayerIterator2)->GetPlayerType() != PT_OUR)
				{	
					// Zistime, ci sa nachadza nejaky super v trojuholniku s bodmi A(hrac s loptou), B, C (presecniky)
					// Ak ano, tak tohto nasho hraca nezaradime do kandidatov na prihravku
					if(pEvPanesMap->IsPointInTriangle((*evPlayerIterator2)->GetPlayerXPosition(), (*evPlayerIterator2)->GetPlayerYPosition(),
						lfMyselfPosX, lfMyselfPosY, lfIntersectX1, lfIntersectY1, lfIntersectX2, lfIntersectY2))
					{
/*						CString strTmp;
  						strTmp.Format("Hracovi (%d) vadi super %d", pEvPlayer->GetPlayerIDNumber(), (*evPlayerIterator2)->GetPlayerIDNumber());
						AfxMessageBox(strTmp);
*/
						bEnemiesInTriangle = true;
						break;
					}
				}
			}

			if(bEnemiesInTriangle == false)
			{
				double lfRadAngle = atan2(b,a);

				// Polomer oblasti kontrolovanej hracom, ktoremu mozno prihrame
				double lfBigCircleRadius = lfPassAreaRadius;

				// Kruznica o polomere chyby prihravky na danu vzdialenost				
				// Vypocitame polomer kruznice (miesta, kde budeme vyhodnocovat vyhodnost prihravky)
				double lfLittleCircleRadius = log(lfDistance) / 4.0;

				// Vypocet uplne vlavo leziacej kruznice, este nenatoceneho hexagonoveho utvaru 
				double lfLeftOffset = pEvPlayer->GetPlayerXPosition();
	
				// Pocet kruznic leziacich vlavo, vpravo, dole alebo hore od stredu
				int nCount = 0;

				while((lfLeftOffset - (2*lfLittleCircleRadius)) > (pEvPlayer->GetPlayerXPosition() - lfBigCircleRadius))
				{
					lfLeftOffset -= (2*lfLittleCircleRadius);
					nCount++;
				}

				int nUpperCircleLimit = (int) (pow(lfBigCircleRadius + lfLittleCircleRadius, 2) / pow(lfLittleCircleRadius, 2));
				PASSPOINT* passArray = new PASSPOINT[nUpperCircleLimit];


				// Pocet kruznic (prehladavacich miest)
				int nCircleCount = 0;

				// Vypocitanie stredov kruzniciek stredovej casti (este nerotovaneho) hexagonoveho utvaru
				double lfY = pEvPlayer->GetPlayerYPosition();
				double tmpOffset = lfLeftOffset;

        int i;

				for(i = 1; i <= (2 * nCount + 1) ; i++)
				{
					double lfTmpX, lfTmpY;

					lfTmpX = tmpOffset;
					lfTmpY = lfY;

					pEvPanesMap->RotatePoint(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), lfTmpX, lfTmpY, lfRadAngle);

					// Ak vypocitany bod je mimo ihriska, tak ho nepotrebujeme
					if(!pEvPanesMap->IsInRectArea(lfTmpX, lfTmpY, -nOriginalPlaygroundWidth/2.0, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0))
						continue;

					if(!pEvPanesMap->IsInRectArea(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), -nOriginalPlaygroundWidth/2.0, -20.16, -36, 20.16))
					{
						passArray[nCircleCount].lfX = lfTmpX;
						passArray[nCircleCount].lfY = lfTmpY;
						nCircleCount++;
					}
//					DrawCircle(pDC, CPoint(lfTmpX, lfTmpY), lfLittleCircleRadius);
					tmpOffset += 2*lfLittleCircleRadius;
				}

				// Nachadza sa nejaky super za nasim hracom?
				bool bBehindPlayer = IsPlayerTypeInTheCircle(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), lfBigCircleRadius, PT_THEIR);

				// Vypocitanie stredov kruzniciek hornej casti (este nerotovaneho) hexagonoveho utvaru
				// Vypocitanie stredov kruzniciek spodnej casti (este nerotovaneho) hexagonoveho utvaru
				for(int j = 1, x = 1; j <= nCount; j++, x++)
				{
					lfLeftOffset = lfLeftOffset + cos(60 * pi / 180)* lfLittleCircleRadius * 2;
					lfY = lfY + sin(60 * pi / 180) * lfLittleCircleRadius * 2;
					
					tmpOffset = lfLeftOffset;
					
					double lfTmpX, lfTmpY;

					for(i = 1; i <= (2 * nCount + 1) - x ; i++)
					{
						// Ak nestoji super za hracom v jeho kontrolovanom kruhu, tak nahravka moze smerovat aj do miest za hraca
						if(!bBehindPlayer)
						{
							lfTmpX = tmpOffset;
							lfTmpY = lfY;

							pEvPanesMap->RotatePoint(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), lfTmpX, lfTmpY, lfRadAngle);
							
							// Ak vypocitany bod je mimo ihriska, tak ho nepotrebujeme
							if(!pEvPanesMap->IsInRectArea(lfTmpX, lfTmpY, -nOriginalPlaygroundWidth/2.0, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0))
								continue;
							
							if(!pEvPanesMap->IsInRectArea(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), -nOriginalPlaygroundWidth/2.0, -20.16, -36, 20.16))
							{
								passArray[nCircleCount].lfX = lfTmpX;
								passArray[nCircleCount].lfY = lfTmpY;
								nCircleCount++;
							}
//							DrawCircle(pDC, CPoint(lfTmpX, lfTmpY), lfLittleCircleRadius);
						}
					
						lfTmpX = tmpOffset;
						lfTmpY = lfY;
						pEvPanesMap->RotatePoint(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), lfTmpX, lfTmpY, lfRadAngle + pi);
						
						// Ak vypocitany bod je mimo ihriska, tak ho nepotrebujeme
						if(!pEvPanesMap->IsInRectArea(lfTmpX, lfTmpY, -nOriginalPlaygroundWidth/2.0, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0))
							continue;
						
						if(!pEvPanesMap->IsInRectArea(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), -nOriginalPlaygroundWidth/2.0, -20.16, -36, 20.16))
						{
							passArray[nCircleCount].lfX = lfTmpX;
							passArray[nCircleCount].lfY = lfTmpY;
							nCircleCount++;
						}
//						DrawCircle(pDC, CPoint(lfTmpX, lfTmpY), lfLittleCircleRadius);

						tmpOffset += 2*lfLittleCircleRadius;
						
					}
				}
	
				// Vyhodnocuje sa ohodnotenia kazdeho ziskaneho bodu a pre kazdeho kandidata sa ulozi max. vysledna hodnota
				double lfTmpPassEvaluation, lfMaxPassEvaluation = 0;

				for(i = 0; i < nCircleCount; i++)
				{
//					out << "[" << passArray[i].lfX << ", " << passArray[i].lfY << "]" << endl;
					double lfTmpDistance = pEvPanesMap->CalculatePaneDistanceFromPlayer(lfMyselfPosX, lfMyselfPosY, passArray[i].lfX, passArray[i].lfY );	
					
					if((pEvPanesMap->IsInRectArea(passArray[i].lfX, passArray[i].lfY, -nOriginalPlaygroundWidth/2.0, -20.16, -36, 20.16)) ||
					((lfTmpDistance <= lfMinPassDistance) || (lfTmpDistance >= lfMaxPassDistance)))
					{	
						bestPasses[nPassCandidates].lfX = passArray[i].lfX;
						bestPasses[nPassCandidates].lfY = passArray[i].lfY;
						bestEvaluatingPasses[nPassCandidates] = 0;

						continue;
					}

					lfTmpPassEvaluation = pEvPanesMap->CalculateSamplingPassLineEvaluation(lfMyselfPosX, lfMyselfPosY, passArray[i].lfX, passArray[i].lfY, pEvPanesMap->GetPaneSize());
					
					if(lfTmpPassEvaluation >= lfMaxPassEvaluation)
					{

						bestPasses[nPassCandidates].lfX = passArray[i].lfX;
						bestPasses[nPassCandidates].lfY = passArray[i].lfY;
						bestEvaluatingPasses[nPassCandidates] = lfMaxPassEvaluation = lfTmpPassEvaluation;
					}
				}
				
				delete [] passArray;
				
				if(lfMaxPassEvaluation > 0)
					passCandidates[nPassCandidates++] = pEvPlayer;
			}
		}
	}

//	out << "Pocet kandidatov na prihravku: " << nPassCandidates << endl;

	if(nPassCandidates == 0)
	{
		ReturnToActualPositions();
		return false;
	}
/*
	ofstream out("Pass Debug.txt"); // Zapis do suboru

	for(int x = 0; x < nPassCandidates; x++)
	{	
		out << "Hrac c." << passCandidates[x]->GetPlayerIDNumber() << " na pozicii (" <<  passCandidates[x]->GetPlayerXPosition() << ", " << passCandidates[x]->GetPlayerYPosition() << ") dostane prihravku s ohodnotenim (" << bestEvaluatingPasses[x] <<") na poziciu (" << bestPasses[x].lfX << ", " << bestPasses[x].lfY << ")" << endl;
	}
	out << endl;
*/
	
/*	out << "PRED ZOSORTOVANIM: " << endl;
	for(int x = 0; x < nPassCandidates; x++)
	{	
		out << "[Vek " << passCandidates[x]->GetPlayerInformationAge() << "] -> Hrac c." << passCandidates[x]->GetPlayerIDNumber() << " na pozicii (" <<  passCandidates[x]->GetPlayerXPosition() << ", " << passCandidates[x]->GetPlayerYPosition() << ") dostane prihravku s ohodnotenim (" << bestEvaluatingPasses[x] <<") na poziciu (" << bestPasses[x].lfX << ", " << bestPasses[x].lfY << ")" << endl;
	}
*/

	
	// Bublinkove triedenie najskor podla veku informacie a az potom podla vysky ohodnotenia
	
	// Prve bublinkove triedenie podla veku informacie
	int nExchangeCount;

	do
	{
		nExchangeCount = 0;

		for(int i = 0; i < nPassCandidates-1; i++)
		{
			if(passCandidates[i]->GetPlayerInformationAge() > passCandidates[i+1]->GetPlayerInformationAge())
			{	
				CEvaluatingPlayer* evTmpPlayer = passCandidates[i];
				passCandidates[i] = passCandidates[i+1];
				passCandidates[i+1] = evTmpPlayer;

				// Musim vymienat aj prislusne najlespsie nahravky patriace vymienanym hracom
				double lfTmpEv = bestEvaluatingPasses[i];
				bestEvaluatingPasses[i] = bestEvaluatingPasses[i+1];
				bestEvaluatingPasses[i+1] = lfTmpEv;

				PASSPOINT tmpBestPass = bestPasses[i];
				bestPasses[i] = bestPasses[i+1];
				bestPasses[i+1] = tmpBestPass;

				nExchangeCount++;
			}
		}

	} while(nExchangeCount != 0);

/*	for( x = 0; x < nPassCandidates; x++)
	{	
		out << "Hrac c." << passCandidates[x]->GetPlayerIDNumber() << " na pozicii (" <<  passCandidates[x]->GetPlayerXPosition() << ", " << passCandidates[x]->GetPlayerYPosition() << ") dostane prihravku s ohodnotenim (" << bestEvaluatingPasses[x] <<") na poziciu (" << bestPasses[x].lfX << ", " << bestPasses[x].lfY << ")" << endl;
	}
	out << endl;
*/
	// Druhe bublinkove triedenie podla vysky ohodnotenia
	do
	{
		nExchangeCount = 0;

		for(int i = 0; i < nPassCandidates-1; i++)
		{
			if(passCandidates[i]->GetPlayerInformationAge() == passCandidates[i+1]->GetPlayerInformationAge())
			{
				if(bestEvaluatingPasses[i] < bestEvaluatingPasses[i+1])
				{	
					double lfTmpEv = bestEvaluatingPasses[i];
					bestEvaluatingPasses[i] = bestEvaluatingPasses[i+1];
					bestEvaluatingPasses[i+1] = lfTmpEv;

					// Musim vymienat aj prislusnych hracov patriacim vymienanym nahravkam
					CEvaluatingPlayer* evTmpPlayer = passCandidates[i];
					passCandidates[i] = passCandidates[i+1];
					passCandidates[i+1] = evTmpPlayer;

					PASSPOINT tmpBestPass = bestPasses[i];
					bestPasses[i] = bestPasses[i+1];
					bestPasses[i+1] = tmpBestPass;

					nExchangeCount++;
				}
			}
		}

	} while(nExchangeCount != 0);

/*	out << "PO ZOSORTOVANI: " << endl;

	for(x = 0; x < nPassCandidates; x++)
	{	
		out << "[Vek " << passCandidates[x]->GetPlayerInformationAge() << "] -> Hrac c." << passCandidates[x]->GetPlayerIDNumber() << " na pozicii (" <<  passCandidates[x]->GetPlayerXPosition() << ", " << passCandidates[x]->GetPlayerYPosition() << ") dostane prihravku s ohodnotenim (" << bestEvaluatingPasses[x] <<") na poziciu (" << bestPasses[x].lfX << ", " << bestPasses[x].lfY << ")" << endl;
	}
*/
//	out << "NAJLEPSI: " << endl;
	
//	out << "[Vek " << passCandidates[0]->GetPlayerInformationAge() << "] -> Hrac c." << passCandidates[0]->GetPlayerIDNumber() << " na pozicii (" <<  passCandidates[0]->GetPlayerXPosition() << ", " << passCandidates[0]->GetPlayerYPosition() << ") dostane prihravku s ohodnotenim (" << bestEvaluatingPasses[0] <<") na poziciu (" << bestPasses[0].lfX << ", " << bestPasses[0].lfY << ")" << endl;
	
/*	double lfDistancePass_Player = pEvPanesMap->CalculatePaneDistanceFromPlayer(bestPasses[0].lfX, bestPasses[0].lfY, passCandidates[0]->GetPlayerXPosition(), passCandidates[0]->GetPlayerYPosition());
			
//	if(lfDistancePass_Player > lfMaxPassAreaRadius)
		out << lfDistancePass_Player;
*///	out.close();

/*	for(int x = 0; x < nPassCandidates; x++)
	{	
		CString strTmp;
  		// strTmp.Format("Kandidat (%d) na pozicii (%lf, %lf)", passCandidates[x]->GetPlayerIDNumber(), passCandidates[x]->GetPlayerXPosition(), passCandidates[x]->GetPlayerYPosition());
		// strTmp.Format("Kandidat (%d) na pozicii (%lf, %lf)", passCandidates[x]->GetPlayerIDNumber(), bestPasses[x].lfX, bestPasses[x].lfY);
		strTmp.Format("Kandidat (%d) s vekom (%d) dostane prihravku s ohodnotenim (%lf) na poziciu (%lf, %lf)", passCandidates[x]->GetPlayerIDNumber(), passCandidates[x]->GetPlayerInformationAge(), bestEvaluatingPasses[x], bestPasses[x].lfX, bestPasses[x].lfY);
		
//		AfxMessageBox(strTmp);
	}
*/

//	finish = clock();
   
/*	CString strTmp;
//	strTmp.Format("Cas = %2.10lf s", ((double)(finish - start) / CLOCKS_PER_SEC));
	strTmp.Format("Prihravka smeruje na (%lf, %lf)", bestPasses[0].lfX, bestPasses[0].lfY);
	AfxMessageBox(strTmp);
*/
//	int nIndex = pEvPanesMap->GenerateRandomIndex(nPassCandidates);;
	
	// Ak hrac stoji na mieste, alebo jeho rychlost je neznama nahravka pojde do vypocitaneho bodu
	if((passCandidates[0]->GetPlayerSpeed().GetLength() == 0) || (pEvPanesMap->IsInRectArea(bestPasses[0].lfX, bestPasses[0].lfY, 35.0, -20.16, 52.5, 20.16)))
	{
		lfPassPosX = bestPasses[0].lfX;
		lfPassPosY = bestPasses[0].lfY;
	}
	else
	{
		Vector v = passCandidates[0]->GetPlayerSpeed();
		Point p(bestPasses[0].lfX, bestPasses[0].lfY);
		p += v; 
		lfPassPosX = p.GetX();
		lfPassPosY = p.GetY();

//		double lfDistancePlayerAndPass = pEvPanesMap->CalculatePaneDistanceFromPlayer(passCandidates[0]->GetPlayerXPosition(), passCandidates[0]->GetPlayerYPosition(), bestPasses[0].lfX, bestPasses[0].lfY);
//		double lfDistancePlayerAndPassRate = lfDistancePlayerAndPass / lfPassAreaRadius * 100;
		
	}
	
	lfPassPosX += passCandidates[0]->GetPlayerInformationAge() * passCandidates[0]->GetPlayerSpeed().GetLength();
	
	ReturnToActualPositions();
	return true;
}

// --------------------------------------------------------------------------------------------------------- //

// Pomocna funkcia, ktora urobi potrebne kroky pred volanim hlavnej funkcie v gradientovej mape 
bool CEvaluatingPlayerList::CalculateOptimalDribblePointAux(double& lfDribblePosX, double& lfDribblePosY, double lfRadius)
{
	bool bResult = true;

	CEvaluatingPlayer* pEvPlayer;

	// Potrebujem odstranit vsetky ohodnotenia mojich hracov, aby mi umelo nevylepsovali vypocet optimalneho driblovacieho bodu
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_OUR)
		{
			pEvPlayer->RemoveAllContributionsFromPanes();
		}
	}
			
	CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();
			
	PredictNextPositions();

	bResult = pEvPanesMap->CalculateOptimalDribblePoint(lfDribblePosX, lfDribblePosY, lfRadius);

	ReturnToActualPositions();

	// Ohodnotenia spoluhracov mozem vratit na ohodnocovaciu mapu
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_OUR)
		{
			pEvPanesMap->TransformPlayerInfluenceIntoEvaluatingPanesMap(pEvPlayer);
		}
	}

	return bResult;

}

// --------------------------------------------------------------------------------------------------------- //

void CEvaluatingPlayerList::CalculateOptimalShootPointAux(double& lfShootPosX, double& lfShootPosY, double lfHalfGoalSize)
{
	CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();
			
	PredictNextPositions();

	pEvPanesMap->CalculateOptimalShootPoint(lfShootPosX, lfShootPosY, lfHalfGoalSize);

	ReturnToActualPositions();
}

// --------------------------------------------------------------------------------------------------------- //

// Pomocna funkcia, ktora urobi potrebne kroky pred volanim hlavnej funkcie v gradientovej mape 
bool CEvaluatingPlayerList::CalculateReceiveBallPositionAux(double& lfMyPosX, double& lfMyPosY, double lfBallPosX, double lfBallPosY)
{
	bool bResult;

	CEvaluatingPlayer* pEvPlayer;

	// Potrebujem odstranit vsetky ohodnotenia mojich hracov, aby mi umelo nevylepsovali vypocet optimalneho driblovacieho bodu
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_OUR)
		{
			pEvPlayer->RemoveAllContributionsFromPanes();
		}
	}
			
	CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();
	
	PredictNextPositions();

	bResult = CalculateReceiveBallPosition(lfMyPosX, lfMyPosY, lfBallPosX, lfBallPosY);

	ReturnToActualPositions();

	// Ohodnotenia spoluhracov mozem vratit na ohodnocovaciu mapu
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_OUR)
		{
			pEvPanesMap->TransformPlayerInfluenceIntoEvaluatingPanesMap(pEvPlayer);
		}
	}

	return bResult;

}

// --------------------------------------------------------------------------------------------------------- //

// Vypocita najvyhodnejsiu poziciu hraca pre nabiehanie si pre prihravku
bool CEvaluatingPlayerList::CalculateReceiveBallPosition(double& lfMyPosX, double& lfMyPosY, double lfBallPosX, double lfBallPosY)
{
	// Maximalna vzdialenost, kedy hraj je ochotny nabiehat
	float fActivationThreshold = 0.9 * lfMaxPassDistance;
/*
	clock_t start, finish;
	start = clock();
*/	
	// Definovanie jedneho z X moznych prihravacich bodov
	typedef struct ReceivePoint
	{
		double lfX;
		double lfY;
	} RECEIVEPOINT;

//	ofstream out("Nabiehanie pre prihravku.txt", ios::app); // Zapis do suboru

	CEvaluatingPanesMap* pEvPanesMap = GetEvaluatingPanesMap();
		 
	double lfDistance = pEvPanesMap->CalculatePaneDistanceFromPlayer(lfMyPosX, lfMyPosY, lfBallPosX, lfBallPosY);
	
	// Hrac musi byt vo vzdialenosti od lopty  v intevale (lfMinPassDistance, lfMaxPassDistance)
	if((lfDistance <= lfMinPassDistance) || (lfDistance >= fActivationThreshold))
		return false;

	// Oblast prihravky (polomer)
	double lfPassAreaRadius;

	// Polomer oblasti prihravania zavisi od vzdialenosti prihravajuceho hraca
	// Cim musi prihravka prekonat vacsiu vzdialenost, tym sa musi prehladat viacero prihravacich pozicii 
	// Namapujem interval <lfMinPassDistance, lfMaxPassDistance> na <lfMinPassAreaRadius, lfMaxPassAreaRadius>
	lfPassAreaRadius = (lfDistance - lfMinPassDistance) / (lfMaxPassDistance - lfMinPassDistance) * (lfMaxPassAreaRadius - lfMinPassAreaRadius) +  lfMinPassAreaRadius;

	// Priesecniky kruznice (oblasti prihravky) a priamky (nahravka)
	double lfIntersectX1, lfIntersectY1, lfIntersectX2, lfIntersectY2; 

	// X-ova zlozka normaloveho vektora
	double lfNormalX, lfNormalY;
	// Y-ova zlozka normalovheo vektora

	// Vypocitaju sa zlozky normaloveho vektora medzi hracom s loptou a potencionalnym miestom pre nabiehanie
	lfNormalX = lfMyPosX - lfBallPosX;
	lfNormalY = lfMyPosY - lfBallPosY;

	// Vseobecna rovnica priamky (ax + by + c = 0)
	// a,b, c - koeficienty	
	double a = lfNormalX;
	double b = lfNormalY;
	double c = -(a * lfMyPosX) - (b * lfMyPosY);
	
	// Ak je smernica priamky definovana (t.j. priamka nie je rovnobezna s osou x)
	if(b != 0)
	{
		// Korene kvadratickej rovnice
		double x1, x2; 
		
		// Vypocitaju sa koeficienty parametrickej rovnice priamky (y = kx + q)
		double k = (-a/b);
		double q = (-c/b);
	
		// Vypocitaju sa koeficienty kvadratickej rovnice (Ax + By + C = 0)
		double A = 1 + pow(k, 2);
		double B = -2 * lfMyPosX + 2 * k * (q - lfMyPosY);
		double C = pow(lfMyPosX,2) + pow((q - lfMyPosY), 2) - pow(lfPassAreaRadius,2);

		// Vypocita sa priesecnik kruznice a priamky
		double lfDiscr = CalculateQuadraticEquation(A, B, C, x1, x2);

		// 2 priesecniky
		if(lfDiscr > 0)
		{
			lfIntersectX1 = x1;
			lfIntersectY1 = k * x1 + q;
			lfIntersectX2 = x2; 
			lfIntersectY2 = k * x2 + q;
/*
			CString strTmp;
  			strTmp.Format("Koren 1: %lf, Koren 2: %lf", x1, x2);
			AfxMessageBox(strTmp);
*/				
		}
		// 1 priesecnik (dotycnica), rydzokvadraticka rovnica
		else if(lfDiscr = 0)
		{
			lfIntersectX1 = lfIntersectX2 = x1;
			lfIntersectY1 = lfIntersectY2 = k * x1 + q;
		}
		// Kvadraticka rovnica nema riesenie (diskriminant < 0)
		else
			return false;
	}	
			// Smernica priamky nie je definovana	
	else
	{
		lfIntersectX1 = lfMyPosX;
		lfIntersectY1 = lfMyPosY + lfPassAreaRadius;
		lfIntersectX2 = lfMyPosX;
		lfIntersectY2 = lfMyPosY - lfPassAreaRadius;
	}
			
					
	double lfRadAngle = atan2(b,a);

	// Polomer oblasti kontrolovanej hracom, ktori si nabieha na jednu z okolitych pozicii v tejto oblasti
	double lfBigCircleRadius = lfPassAreaRadius;

	// Kruznica o polomere chyby prihravky na danu vzdialenost				
	// Vypocitame polomer kruznice (miesta, kde budeme vyhodnocovat vyhodnost nabiehania)
	double lfLittleCircleRadius = log(lfDistance) / 2.0;

	// Vypocet uplne vlavo leziacej kruznice, este nenatoceneho hexagonoveho utvaru 
	double lfLeftOffset = lfMyPosX;

	// Pocet kruznic leziacich vlavo, vpravo, dole alebo hore od stredu
	int nCount = 0;

	while((lfLeftOffset - (2*lfLittleCircleRadius)) > (lfMyPosX - lfBigCircleRadius))
	{
		lfLeftOffset -= (2*lfLittleCircleRadius);
		nCount++;
	}

	int nUpperCircleLimit = (int) (pow(lfBigCircleRadius + lfLittleCircleRadius, 2) / pow(lfLittleCircleRadius, 2));
	RECEIVEPOINT* passArray = new RECEIVEPOINT[nUpperCircleLimit];

	// Pocet kruznic (prehladavacich miest)
	int nCircleCount = 0;

	// Vypocitanie stredov kruzniciek stredovej casti (este nerotovaneho) hexagonoveho utvaru
	double lfY = lfMyPosY;
	double tmpOffset = lfLeftOffset;

  int i;

	for(i = 1; i <= (2 * nCount + 1) ; i++)
	{
		double lfTmpX, lfTmpY;

		lfTmpX = tmpOffset;
		lfTmpY = lfY;

		pEvPanesMap->RotatePoint(lfMyPosX, lfMyPosY, lfTmpX, lfTmpY, lfRadAngle);

		// Ak vypocitany bod je mimo ihriska, tak ho nepotrebujeme
		if(!pEvPanesMap->IsInRectArea(lfTmpX, lfTmpY, -nOriginalPlaygroundWidth/2.0, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0))
			continue;
		
		passArray[nCircleCount].lfX = lfTmpX;
		passArray[nCircleCount].lfY = lfTmpY;
		nCircleCount++;
		
//		DrawCircle(pDC, CPoint(lfTmpX, lfTmpY), lfLittleCircleRadius);
		tmpOffset += 2*lfLittleCircleRadius;
	}

	// Nachadza sa nejaky super za nasim hracom?
	bool bBehindPlayer = IsPlayerTypeInTheCircle(lfMyPosX, lfMyPosY, lfBigCircleRadius, PT_THEIR) && 
		IsPlayerTypeInTheCircle(lfMyPosX, lfMyPosY, lfBigCircleRadius, PT_NEARBY) &&
		IsPlayerTypeInTheCircle(lfMyPosX, lfMyPosY, lfBigCircleRadius, PT_UNKNOWN);

	// Vypocitanie stredov kruzniciek hornej casti (este nerotovaneho) hexagonoveho utvaru
	// Vypocitanie stredov kruzniciek spodnej casti (este nerotovaneho) hexagonoveho utvaru
	for(int j = 1, x = 1; j <= nCount; j++, x++)
	{
		lfLeftOffset = lfLeftOffset + cos(60 * pi / 180)* lfLittleCircleRadius * 2;
		lfY = lfY + sin(60 * pi / 180) * lfLittleCircleRadius * 2;
		
		tmpOffset = lfLeftOffset;
		
		double lfTmpX, lfTmpY;

		for(i = 1; i <= (2 * nCount + 1) - x ; i++)
		{
			// Ak nestoji super za hracom v jeho kontrolovanom kruhu, tak hrac moze nabiehat aj do miest za hraca
			if(!bBehindPlayer)
			{
				lfTmpX = tmpOffset;
				lfTmpY = lfY;

				pEvPanesMap->RotatePoint(lfMyPosX, lfMyPosY, lfTmpX, lfTmpY, lfRadAngle);
				
				// Ak vypocitany bod je mimo ihriska, tak ho nepotrebujeme
				if(!pEvPanesMap->IsInRectArea(lfTmpX, lfTmpY, -nOriginalPlaygroundWidth/2.0, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0))
					continue;
						
				passArray[nCircleCount].lfX = lfTmpX;
				passArray[nCircleCount].lfY = lfTmpY;
				nCircleCount++;
				
//				DrawCircle(pDC, CPoint(lfTmpX, lfTmpY), lfLittleCircleRadius);
			}
		
			lfTmpX = tmpOffset;
			lfTmpY = lfY;
			pEvPanesMap->RotatePoint(lfMyPosX, lfMyPosY, lfTmpX, lfTmpY, lfRadAngle + pi);
			
			// Ak vypocitany bod je mimo ihriska, tak ho nepotrebujeme
			if(!pEvPanesMap->IsInRectArea(lfTmpX, lfTmpY, -nOriginalPlaygroundWidth/2.0, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0))
				continue;
			
			passArray[nCircleCount].lfX = lfTmpX;
			passArray[nCircleCount].lfY = lfTmpY;
			nCircleCount++;
			
//			DrawCircle(pDC, CPoint(lfTmpX, lfTmpY), lfLittleCircleRadius);
			tmpOffset += 2*lfLittleCircleRadius;
		}
	}
	
	// Vyhodnotia sa jednotlive body z hladiska vyhodnosti nabiehania
	double lfTmpPassEvaluation, lfMaxPassEvaluation = 0;

	for(i = 0; i < nCircleCount; i++)
	{
		double lfTmpDistance = pEvPanesMap->CalculatePaneDistanceFromPlayer(lfBallPosX, lfBallPosY, passArray[i].lfX, passArray[i].lfY );	

		// TODO: Test na ofsajd
/*
		if((pEvPanesMap->OFSAJD(passArray[i].lfX, passArray[i].lfY, ) ||
		((lfTmpDistance <= lfMinPassDistance) || (lfTmpDistance >= lfMaxPassDistance)))
		{	
			bestPasses[nPassCandidates].lfX = passArray[i].lfX;
			bestPasses[nPassCandidates].lfY = passArray[i].lfY;
			bestEvaluatingPasses[nPassCandidates] = 0;

			continue;
		}
*/
		lfTmpPassEvaluation = pEvPanesMap->CalculateSamplingPassLineEvaluation(lfBallPosX, lfBallPosY, passArray[i].lfX, passArray[i].lfY, pEvPanesMap->GetPaneSize());
//		out << "[" << passArray[i].lfX << ", " << passArray[i].lfY << "]" << " " << lfTmpPassEvaluation << endl;	

//		CString strTmp;
//		strTmp.Format("Bod (%lf, %lf) ma ohodnotenie: (%lf)", lfMyPosX, lfMyPosY, lfTmpPassEvaluation);
//		AfxMessageBox(strTmp);

		// Konstanta, ktorou sa prenasobi ohodnotenie nahravky na nabiehavacie miesto 
		double lfDistanceBonus = 1;
		// Minimalna vzdialenost, kedy sa o bonuse zacina uvazovat. Zaroven je na tuto vzdialenost bonus najvacsi.
		double lfMinDistanceForBonus = 12;
	
		// Vypocet bonusu. Od lfMinDistanceForBonus vzdialenosti bonus postupne linearne klesa na 1.
		if(lfTmpDistance >= lfMinDistanceForBonus)
		{
			lfDistanceBonus = 1.1 - (lfTmpDistance - lfMinDistanceForBonus) / (fActivationThreshold - lfMinDistanceForBonus) * 1.095;
		}
		else if(lfTmpDistance <= lfMinPassDistance)
		{
			lfDistanceBonus = 0.0;
		}
		else if(lfTmpDistance < lfMinDistanceForBonus)
		{
			lfDistanceBonus = lfTmpDistance / lfMinDistanceForBonus;
		}

/*		// Nabiehavat by si hraci mali skor pred hraca s lotptou, takze znehodnotime ohodnotenia pozicii za loptou
		if(lfBallPosX > passArray[i].lfX)
		{
			lfDistanceBonus *= 0.5;
		}
*/	
		lfTmpPassEvaluation *= lfDistanceBonus;
		
		if(lfTmpPassEvaluation >= lfMaxPassEvaluation)
		{

			lfMyPosX = passArray[i].lfX;
			lfMyPosY = passArray[i].lfY;
			
			lfMaxPassEvaluation = lfTmpPassEvaluation;
		}
	}
	
	delete [] passArray;

/*	if(lfMaxPassEvaluation > 0)
		out << "Maximalne ohodnotenie: " << lfMaxPassEvaluation << endl;
	else if(lfMaxPassEvaluation == 0)
		return false;

	finish = clock();
   
	CString strTmp;
	strTmp.Format("Cas = %2.10lf s", ((double)(finish - start) / CLOCKS_PER_SEC));
	AfxMessageBox(strTmp);
*/	
	return true;
}

// --------------------------------------------------------------------------------------------------------- //

bool CEvaluatingPlayerList::CheckDuplicityPlayerInfo(CEvaluatingPlayer* pTestPlayer)
{
	int nRemoveCount = 0;

	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);
		CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap(); 
	
		double lfDistance = pEvPanesMap->CalculatePaneDistanceFromPlayer(pTestPlayer->GetPlayerXPosition(), pTestPlayer->GetPlayerYPosition(), pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition());
		if (lfDistance < lfMaxVisualInfoNoise)
		{
			if((pEvPlayer->GetPlayerType() == PT_NEARBY) || (pEvPlayer->GetPlayerType() == PT_UNKNOWN))
			{
				RemovePlayerInformation(pEvPlayer);
				evPlayerIterator = GetEvPlayerIteratorBegin();
				nRemoveCount++;
				
				continue;
			}
			
			if((pTestPlayer->GetPlayerType() == PT_NEARBY) || (pTestPlayer->GetPlayerType() == PT_UNKNOWN))
			{
				if(((pEvPlayer->GetPlayerType() == PT_OUR) || (pEvPlayer->GetPlayerType() == PT_THEIR)) && (lfDistance <= lfMaxVisualInfoNoise/4.0))
				{	
					
					
/*					if((pTestPlayer->GetPlayerType() == PT_NEARBY))
						DBG("[NEARBY] Menim hraca (%lf, %lf) s cislom %d na ", pTestPlayer->GetPlayerXPosition(), pTestPlayer->GetPlayerYPosition(), pTestPlayer->GetPlayerIDNumber());
					else if((pTestPlayer->GetPlayerType() == PT_UNKNOWN))
						DBG("[UNKNOWN] Menim hraca (%lf, %lf) s cislom %d na ", pTestPlayer->GetPlayerXPosition(), pTestPlayer->GetPlayerYPosition(), pTestPlayer->GetPlayerIDNumber());
					
					if((pEvPlayer->GetPlayerType() == PT_OUR))
						DBG("[OUR] hraca (%lf, %lf) s cislom %d na :\n", pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), pEvPlayer->GetPlayerIDNumber());
					else if((pEvPlayer->GetPlayerType() == PT_THEIR))
						DBG("[THEIR] hraca (%lf, %lf) s cislom %d na :\n", pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), pEvPlayer->GetPlayerIDNumber());

					pTestPlayer->SetPlayerType(pEvPlayer->GetPlayerType());
					pTestPlayer->SetPlayerIDNumber(pEvPlayer->GetPlayerIDNumber());					
					
					RemovePlayerInformation(pEvPlayer);
					evPlayerIterator = GetEvPlayerIteratorBegin();
					nRemoveCount++;

					continue;
*/				}
			}

			if(((pTestPlayer->GetPlayerType() == PT_OUR) && (pEvPlayer->GetPlayerType() != PT_THEIR)) ||
				((pTestPlayer->GetPlayerType() == PT_THEIR) && (pEvPlayer->GetPlayerType() != PT_OUR)))
			{
				RemovePlayerInformation(pEvPlayer);
				evPlayerIterator = GetEvPlayerIteratorBegin();
				nRemoveCount++;

				continue;
			}
		}		
	}

	if(nRemoveCount > 0)
		return true;
	else
		return false;
}
// --------------------------------------------------------------------------------------------------------- //

// Funkcia odporuci hraca, ktoremu by sa malo nahrat pri zahravani typu KickOff podla ohodnoteni v jeho oblasti.
// V pripade rovnakych ohodnoteni sa odporuca nahodne vybrany hrac.
CEvaluatingPlayer* CEvaluatingPlayerList::GetKickOffPlayer()
{
	CEvaluatingPlayer* PlayerIndex[11];
	double lfPlayerEvArea[11];
	int nPlayerInfoCount = -1;

	memset(lfPlayerEvArea, 0, sizeof(lfPlayerEvArea));

	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		CEvaluatingPlayer* pEvPlayer = *evPlayerIterator;

		if(pEvPlayer->GetPlayerType() == PT_OUR)
		{		
			CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();

			if(pEvPanesMap->IsInRectArea(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(),
				-10, -nOriginalPlaygroundHeight/2.0, nOriginalPlaygroundWidth/2.0, nOriginalPlaygroundHeight/2.0 ))
				continue;
			
			nPlayerInfoCount++;
			PlayerIndex[nPlayerInfoCount] = pEvPlayer;
			lfPlayerEvArea[nPlayerInfoCount] = pEvPlayer->CalculateMaxEvaluation();
/*
	CString strTmp;
	strTmp.Format(" Hrac c.%d ma max. ohodnotnie %lf", nPlayerIndex[nPlayerInfoCount], lfPlayerEvArea[nPlayerInfoCount]);
	AfxMessageBox(strTmp);
*/		
		}
	}
	// Ak v zozname neboli ziadny hraci, tak vrat -1. (Toto by sa nemalo stat)
	if(nPlayerInfoCount == -1)
		return NULL;

	CEvaluatingPlayer* pEvBestPlayer = PlayerIndex[0];

	double lfBestPlayerEvArea = lfPlayerEvArea[0];
	
	for(int i = 0; i <= nPlayerInfoCount; i++)
	{
		if(lfPlayerEvArea[i] > lfBestPlayerEvArea)
		{
			pEvBestPlayer = PlayerIndex[i];
			lfBestPlayerEvArea = lfPlayerEvArea[i];
		}
		else if(lfPlayerEvArea[i] == lfBestPlayerEvArea)
		{		
			// Vyberie sa jeden hrac nahodne
			CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();
			
			// Ak je index 1, tak sa ulozi novy najlepsi hrac, inak sa nic nemeni
			if(pEvPanesMap->GenerateRandomIndex(2) == 1)
			{
				pEvBestPlayer = PlayerIndex[i];
				lfBestPlayerEvArea = lfPlayerEvArea[i];
			}
		}
	}
/*			
	CString strTmp;
	strTmp.Format("Najlepsi Hrac c.%d ma max. ohodnotnie %lf", pEvBestPlayer->GetPlayerIDNumber(), lfBestPlayerEvArea);
	AfxMessageBox(strTmp);
*/			
		
	return pEvBestPlayer;

}

// --------------------------------------------------------------------------------------------------------- //

// Funkcia sluzi na inkrementovanie zaznamenanaj informacii o hracovi o 1 cyklus
void CEvaluatingPlayerList::IncrementPlayerInformationAge()
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{	
		int nPIAge = (*evPlayerIterator)->GetPlayerInformationAge();

		(*evPlayerIterator)->SetPlayerInformationAge(++nPIAge);
	}

	// Vyhodenie informacii o hracovi starsej ako N cyklov
	RemoveOldPlayerInformation(nMaxAgeInformation);
}

// --------------------------------------------------------------------------------------------------------- //

// Vlozi informaciu o hracovi do zoznamu
void CEvaluatingPlayerList::InsertPlayerInformation(CEvaluatingPlayer* pEvPlayer)
{
	CEvaluatingPlayer* pOldEvalPlayer;

	// Zisti sa najskor, ci uz hrac s takym typom a cislom v zozname nie je
	// Hracom s cislom 0 moze byt v zozname viac, preto v nom nehladame
	if(pEvPlayer->GetPlayerIDNumber() == 0)
		pOldEvalPlayer = NULL;
	else
		pOldEvalPlayer = IsPlayerInTheList(pEvPlayer->GetPlayerType(), pEvPlayer->GetPlayerIDNumber());
	
	// Ak tam taky hrac je, treba ho odstranit zo zoznamu a odstranit jeho vplyvy na polickach
	if(pOldEvalPlayer != NULL)
	{
		RemovePlayerInformation(pOldEvalPlayer);
		pOldEvalPlayer = NULL;
	}
	// Skontroluj vzdialenost tohto hraca od vsetkych s dresom 0 v zozname a ak tam je, vyhod hraca s dresom 0.
	else
		CheckDuplicityPlayerInfo(pEvPlayer);

	if(pEvPlayer->GetPlayerIDNumber() == 0)
	{
		// Ak ma hrac dres 0, tak ho uchovame v zozname menej cyklov (Iba 1 cyklus)	
		pEvPlayer->SetPlayerInformationAge(nMaxAgeInformation - 1);
	}

	// Premietni hracov vplyv do ciselnej mapy ohodnocovacich policok
	CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap(); 
	pEvPanesMap->TransformPlayerInfluenceIntoEvaluatingPanesMap(pEvPlayer);
	
	playerList.push_back(pEvPlayer);
}

// --------------------------------------------------------------------------------------------------------- //

// Nachadza sa hociktory hrac daneho typu v kruznici so suradnicami x,y a polomerom r?
bool CEvaluatingPlayerList::IsPlayerTypeInTheCircle(double lfCircleCenterX, double lfCircleCenterY, double lfCircleRadius, PlayerType emPlayerType)
{
	// Tato funkcia sa vola v inej funkcii, ktora tiez vyuziva iteratory. Preto potrebujem definovat iny iterator, aby sa neovplyvnovali.
	for(list<CEvaluatingPlayer*>::iterator evPlayerIterator2 = GetEvPlayerIteratorBegin(); evPlayerIterator2 != GetEvPlayerIteratorEnd(); evPlayerIterator2++)
	{		
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator2);
		CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap(); 

		if(pEvPlayer->GetPlayerType() == emPlayerType)
		{
			if (pEvPanesMap->CalculatePaneDistanceFromPlayer(lfCircleCenterX, lfCircleCenterY, pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition()) <= lfCircleRadius)
			{
				switch(emPlayerType)
				{
					case PT_THEIR:
					case PT_NEARBY:
					case PT_UNKNOWN:
						return true;
						break;

					default:
 						break;	
				}
			}		
		}
	}
	return false;
}

// --------------------------------------------------------------------------------------------------------- //

// Zisti, ci hrac daneho typu a s danym cislom uz v zozname je
// Ak ano tak vrati nanho pointer, ak nie vrati NULL
CEvaluatingPlayer* CEvaluatingPlayerList::IsPlayerInTheList(PlayerType ePType, int nIDnumber)
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{	
		
		if(((*evPlayerIterator)->GetPlayerType() == ePType) && ((*evPlayerIterator)->GetPlayerIDNumber() == nIDnumber))
		{		
			return (*evPlayerIterator);
		}
	}
	return NULL;
}

// --------------------------------------------------------------------------------------------------------- //

// Vrati true, ak v mojom okoli nie su nejaki blizki, neznami alebo superovi hraci
bool CEvaluatingPlayerList::NoEnemiesAround(Point myPos)
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_NEARBY)
		{	
			return false;
		}
		else if(pEvPlayer->GetPlayerType() != PT_OUR)
		{
			Point enemyPos(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition());
			
			if ((enemyPos - myPos).GetLength() <= 8.0f && (enemyPos - myPos).GetAngle().GetAbsDeg() < 90) 
				return false;
		}
	}

	return true;
}
// --------------------------------------------------------------------------------------------------------- //

// Vrati true, ak v mojom okoli su nejaki blizki hraci
bool CEvaluatingPlayerList::NearbyEnemiesAround(Point myPos)
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_NEARBY)
		{	
			return true;
		}
	}

	return false;
}

// --------------------------------------------------------------------------------------------------------- //

// Mam nejakych spoluhracov v superovom pokutovom pasme?
bool CEvaluatingPlayerList::OurPlayersInEnemyPenaltyArea()
{
	CEvaluatingPanesMap* pEvPanesMap =  GetEvaluatingPanesMap();

	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{		
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);

		if(pEvPlayer->GetPlayerType() == PT_OUR)
		{	
			if(pEvPanesMap->IsInRectArea(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition(), 36.0, -20.16, nOriginalPlaygroundWidth/2.0, 20.16))
				return true;
		}
	}
	
	return false;
}

// --------------------------------------------------------------------------------------------------------- //

// Nastavi pozicie vsetkych hracov, tak ako budu v dalsom kroku zapasu
void CEvaluatingPlayerList:: PredictNextPositions()
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{			
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);
			 
		// Predpokladame, ze hrac bude v dalsom cykle posunuty o jeho rychlost
		int nInformAge = 0; // pEvPlayer->GetPlayerInformationAge();

		Vector tmpSpeed = pEvPlayer->GetPlayerSpeed();
		Point newPosition(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition());
		newPosition += tmpSpeed * (nInformAge + 1);
		pEvPlayer->SetPlayerXPosition(newPosition.GetX());
		pEvPlayer->SetPlayerYPosition(newPosition.GetY());
	}
}

// --------------------------------------------------------------------------------------------------------- //

// Nastavi pozicie vsetkych hracov na povodne hodnoty
void CEvaluatingPlayerList::ReturnToActualPositions()
{
	for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
	{			
		CEvaluatingPlayer* pEvPlayer = (*evPlayerIterator);
	
		int nInformAge = 0; // pEvPlayer->GetPlayerInformationAge();

		Vector tmpSpeed = pEvPlayer->GetPlayerSpeed();
		Point oldPosition(pEvPlayer->GetPlayerXPosition(), pEvPlayer->GetPlayerYPosition());
		oldPosition -= tmpSpeed * (nInformAge + 1);
		pEvPlayer->SetPlayerXPosition(oldPosition.GetX());
		pEvPlayer->SetPlayerYPosition(oldPosition.GetY());
	}
}

// --------------------------------------------------------------------------------------------------------- //

// Odstrani vsetky informacie o hracoch urciteho typu
void CEvaluatingPlayerList::RemoveAllPlayerTypeInformation(PlayerType emPlayerType)
{
	bool bListChange;
	do
	{
		bListChange = false;

		for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
		{		
			if((*evPlayerIterator)->GetPlayerType() == emPlayerType)
			{		
				delete (*evPlayerIterator);
				evPlayerIterator = playerList.erase(evPlayerIterator);
				bListChange = true;
				break;
			}
		}
	} while(bListChange);
}

// --------------------------------------------------------------------------------------------------------- //

// Odstrani informaciu o hracovi zo zoznamu
void CEvaluatingPlayerList::RemoveOldPlayerInformation(int nMaxCycles)
{
	bool bListChange;
	do
	{
		bListChange = false;

		for(evPlayerIterator = GetEvPlayerIteratorBegin(); evPlayerIterator != GetEvPlayerIteratorEnd(); evPlayerIterator++)
		{		
			if((*evPlayerIterator)->GetPlayerInformationAge() > nMaxCycles)
			{		
				delete (*evPlayerIterator);
				evPlayerIterator = playerList.erase(evPlayerIterator);
				bListChange = true;
				break;
			}
		}
	} while(bListChange);
}

// --------------------------------------------------------------------------------------------------------- //

// Odstrani informaciu o hracovi zo zoznamu
void CEvaluatingPlayerList::RemovePlayerInformation(CEvaluatingPlayer* pEvPlayer)
{
	list<CEvaluatingPlayer*>::iterator	tmpEvPlayerIterator;

	for(tmpEvPlayerIterator = GetEvPlayerIteratorBegin(); tmpEvPlayerIterator != GetEvPlayerIteratorEnd(); tmpEvPlayerIterator++)
	{			
		if(((*tmpEvPlayerIterator)->GetPlayerType() == pEvPlayer->GetPlayerType()) && ((*tmpEvPlayerIterator)->GetPlayerIDNumber() == pEvPlayer->GetPlayerIDNumber()))
		{		
			delete (*tmpEvPlayerIterator);
			playerList.erase(tmpEvPlayerIterator);
			return;
		}
	}

}

// --------------------------------------------------------------------------------------------------------- //

